home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / Talking Clock Pro™ 2.0.1 / Talking Clock Pro Source / Extension / Headers / x.h < prev   
Encoding:
Text File  |  1993-09-03  |  6.8 KB  |  225 lines  |  [TEXT/CWIE]

  1. /*
  2.  * x.h ©1993 Jon Wätte (h+@nada.kth.se) All Rights Reserved.
  3.  * Please read the paragraph marked $$$ below before using this
  4.  * source file.
  5.  *
  6.  * v1.0 930826 - Initial Release
  7.  */
  8.  
  9. /*
  10.  * This try/fail system was inspired by how the Think Class Library
  11.  * exception mechanism works. No code was taken from the TCL, and I have
  12.  * not even studied the source of the TCL exception mechanism.
  13.  *
  14.  * You use it by encapsulating code that might fail in
  15.  *
  16.  * TRY {
  17.  *    <code>
  18.  * } CATCH {
  19.  *    <error handler>
  20.  * } DONE ;
  21.  *
  22.  * If your error handler does not want to keep doing exceptions
  23.  * that this exception might be encapsulated in, it should look
  24.  * something like this:
  25.  * ...
  26.  * } CATCH {
  27.  *    <error handler>
  28.  *    NO_PROPAGATE ;
  29.  * } DONE ;
  30.  *
  31.  * There are cases where you want to do something like restore the state
  32.  * of a handle both when catching failures and when done with the critical
  33.  * section normally - in that case, you can use CLEANUP instead of CATCH:
  34.  *
  35.  *    void
  36.  *    Function ( Handle h ) {
  37.  *
  38.  *    char state = HGetState ( h ) ;
  39.  *
  40.  *        HLock ( h ) ;
  41.  *        TRY {
  42.  *            DoSomethingTo ( * h ) ;
  43.  *        } CLEANUP {
  44.  *            HSetState ( h , state ) ;
  45.  *        } DONE ;
  46.  *
  47.  * The code between CLEANUP and DONE will be executed for both exception
  48.  * cases and normal execution - HOWEVER, an exception will jump to the next
  49.  * upward exception handler at DONE while the normal code will continue.
  50.  * You can modify this behaviour with NO_PROPAGATE ;
  51.  *
  52.  * To trigger an exception, you call FailErr(e) with a non-0 e, or you call
  53.  * FailNil(p) with a NULL p (in which case a -108 error is generated) If you
  54.  * want to know what error you are handling in an error handler, it is stored
  55.  * in the __err variable that is in scope in the whole TRY { } CATCH { } DONE
  56.  * construct. NO_PROPAGATE ; sets this variable to 0.
  57.  *
  58.  * If you #define FAILINFO below, you will additionally have a C string with
  59.  * the name of the offending file in __err_file and an int with the offending
  60.  * line number in __err_line. This option will generate more string data in
  61.  * your program (one string per call of FailErr or FailNil) so you may want to
  62.  * turn it off before release (and write your failure handling routine conditional
  63.  * on FAILINFO)
  64.  *
  65.  * If the outermost failure layer reaches DONE, bad things happen. This is because
  66.  * you are supposed to provide a failure handler there and call NO_PROPAGATE. My
  67.  * application typically looks like:
  68.  *
  69.  *    void
  70.  *    main ( void ) {
  71.  *
  72.  *        InitToolbox ( ) ;
  73.  *        TRY {
  74.  *            InitApp ( ) ;
  75.  *            while ( ! quit ) {
  76.  *                TRY {
  77.  *                    ProcessEvent ( ) ;
  78.  *                } CATCH {
  79.  *                    ReportError ( __err ) ;
  80.  *                    NO_PROPAGATE ;
  81.  *                } DONE ;
  82.  *            }
  83.  *        } CLEANUP {
  84.  *            QuitApp ( ) ;
  85.  *            if ( __err ) {
  86.  *                ReportStartQuitErr ( __err ) ;
  87.  *                ExitToShell ( ) ;
  88.  *            }
  89.  *        } DONE ;
  90.  *    }
  91.  *
  92.  * ReportError might look something like: (NOTE: The use of ParamText is NOT
  93.  * WorldScript compatible!)
  94.  *
  95.  *    static void
  96.  *    ReportError ( short errCode , Boolean toQuit ) {
  97.  *
  98.  *    StringHandle h = GetString ( errCode ) ;
  99.  *    Str15 code ;
  100.  *    StringHandle num ;
  101.  *    Str31 fileStr ;
  102.  *    Str15 lineStr ;
  103.  *
  104.  *        DisposeHandle ( err_safeguard ) ; /* Handle allocated in InitApp to give us some room * /
  105.  *        if ( ! h ) {
  106.  *            h = GetString ( 129 ) ; /* What do we do if this fails !? * /
  107.  *        }
  108.  *        HLock ( ( Handle ) h ) ;
  109.  *        NumToString ( errCode , code ) ;
  110.  *        num = GetString ( 130 ) ;
  111.  *        if ( num ) {
  112.  *            PtrAndHand ( ( Ptr ) & code [ 1 ] , ( Handle ) num , code [ 0 ] ) ;
  113.  *            * * num += code [ 0 ] ;
  114.  *            HLock ( ( Handle ) num ) ;
  115.  *        }
  116.  *
  117.  *    #ifdef FAILINFO
  118.  *        NumToString ( __err_line , lineStr ) ;
  119.  *        CopyC2P ( __err_file , fileStr ) ; /* Make fileStr the Pascal version of __err_file * /
  120.  *    #else
  121.  *        lineStr [ 0 ] = fileStr [ 0 ] = 0 ;
  122.  *    #endif
  123.  *
  124.  *        ParamText ( h ? * h : NULL , num ? * num : NULL , fileStr , lineStr ) ;
  125.  *        if ( num ) {
  126.  *            ReleaseResource ( ( Handle ) num ) ;
  127.  *        }
  128.  *        if ( h ) {
  129.  *            ReleaseResource ( ( Handle ) h ) ;
  130.  *        }
  131.  *        if ( ! InFront ( ) ) {
  132.  *            Notify ( ) ; /* Post notification since we're in the background * /
  133.  *        }
  134.  *        Alert ( 128 , NULL ) ; /* Could use a filterProc here * /
  135.  *        HiliteMenu ( 0L ) ; /* For failures during menu selections * /
  136.  *        ParamText ( NULL , NULL , NULL , NULL ) ;
  137.  *        err_safeguard = NewHandle ( 1024 ) ;
  138.  *    }
  139.  *
  140.  * This exception system is written COMPLETELY in ANSI C. It is also FreeWare
  141.  * in the sense that you may use it, modified or not, in any product you
  142.  * make, as long as you send the author (me, Jon Wätte, h+@nada.kth.se) a
  143.  * copy of any product you make using this exception system. You may *NOT*
  144.  * distribute copies of these files (x.c and x.h) that are changed, renamed
  145.  * or in any other way modified from the originals as released by me.
  146.  *
  147.  * $$$ Also, please note, that I neither CAN nor WILL take any responsibility
  148.  * for your use of this source code; you use it solely AT YOUR OWN RISK, and
  149.  * if your use of this code or any derivative thereof results in damages to
  150.  * you or a third party, you are solely responsible for covering all such
  151.  * damages and costs related thereto. This code is provided by the author free
  152.  * of charge. IF THE ABOVE LIMITATION OF JON WÄTTE'S RESPONSIBILITY IS NOT LEGAL
  153.  * WHERE YOU USE OR PUBLISH THIS CODE OR THE RESULTS THEREOF, you are STRICTLY
  154.  * FORBIDDEN to use this code, ON THE PENALTY OF USD $1,000,000,000 (one
  155.  * billion US dollars) or SEK 10,000,000,000 (ten billion Swedish Crowns)
  156.  * whichever is greater, in damages for breach of contract and copyright
  157.  * infringement. I MEAN IT.
  158.  *
  159.  * If you want to fix bugs, CONTACT ME and I will incorporate the bug fix in
  160.  * the next general release.
  161.  *
  162.  */
  163.  
  164. #pragma once
  165. #ifndef x_h
  166. # define x_h
  167.  
  168. /* Define FAILINFO to get information about where something went wrong
  169.  * in failure alerts.
  170.  * Comment it out to save global/string data space
  171.  */
  172. # define FAILINFO
  173.  
  174. # include <setjmp.h>
  175. # include <Types.h>
  176.  
  177. # ifdef FAILINFO
  178. void __FailNil ( void * , char * , int ) ;
  179. void __FailErr ( OSErr , char * , int ) ;
  180. #  define FailNil(x) __FailNil(x,__FILE__,__LINE__)
  181. #  define FailErr(x) __FailErr(x,__FILE__,__LINE__)
  182. extern char * __err_file ;
  183. extern int __err_line ;
  184. # else
  185. void FailNil ( void * ) ;
  186. void FailErr ( OSErr ) ;
  187. # endif
  188.  
  189. #ifdef applec
  190. #define JBT long *
  191. #define JB2CB
  192. #define CB2JB
  193. #else
  194. #define JBT jmp_buf
  195. #define JB2CB &
  196. #define CB2JB *
  197. #endif
  198.  
  199. extern JBT * __cur_buf ;
  200.  
  201. # define TRY \
  202.     { short __err ; jmp_buf __jbuf ; JBT * __last_top = __cur_buf ; \
  203.         if ( ! ( __err = setjmp ( __jbuf ) ) ) { __cur_buf = JB2CB __jbuf ;
  204.  
  205. # define CATCH \
  206.         } else { __cur_buf = __last_top ;
  207.  
  208. # define CLEANUP \
  209.         __err = 0 ; goto __cleanup ; } else { __cur_buf = __last_top ; __cleanup :
  210.  
  211. # define DONE \
  212.             if ( __err ) { \
  213.                 if ( ! __cur_buf ) { DebugStr ( "\pException Underflow" ) ; } ; \
  214.                 longjmp ( CB2JB __cur_buf , __err ) ;\
  215.             } \
  216.         } \
  217.         __cur_buf = __last_top ; \
  218.     }
  219.  
  220. # define NO_PROPAGATE \
  221.     __err = 0 ;
  222.  
  223. #endif /* x_h */
  224.  
  225.